/* Copyright (c) 2003 The Nutch Organization. All rights reserved. */ /* Use subject to the conditions in http://www.nutch.org/LICENSE.txt. */ package net.nutch.util; import java.util.*; import java.net.URL; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.util.logging.Logger; import javax.xml.parsers.*; import org.w3c.dom.*; /** Provides access to Nutch configuration parameters. * * <p>Default values for all parameters are specified in a file named * <tt>nutch-default.xml</tt> located on the classpath. Overrides for these * defaults should be in an optional file named <tt>nutch-site.xml</tt>, also * located on the classpath. Typically these files reside in the * <tt>conf/</tt> subdirectory at the top-level of a Nutch installation. */ public class NutchConf { private static final Logger LOG = LogFormatter.getLogger("net.nutch.util.NutchConf"); private static List resourceNames = new ArrayList(); private static Properties properties; static { resourceNames.add("nutch-default.xml"); resourceNames.add("nutch-site.xml"); } /** Adds a resource name to the chain of resources read. The first resource * is always <tt>nutch-default.xml</tt>, and the last is always * <tt>nutch-site.xml</tt>. New resources are inserted between these, so * they can override defaults, but not site-specifics. */ public static synchronized void addConfResource(String name) { resourceNames.add(resourceNames.size()-1, name); // add second to last properties = null; // trigger reload } private static synchronized Properties getProps() { if (properties == null) { properties = new Properties(); ListIterator i = resourceNames.listIterator(); while (i.hasNext()) { loadResource((String)i.next(), i.nextIndex()==resourceNames.size()); } } return properties; } /** Returns the value of the <code>name</code> property, or null if no * such property exists. */ public static String get(String name) { return getProps().getProperty(name);} /** Returns the value of the <code>name</code> property. If no such property * exists, then <code>defaultValue</code> is returned. */ public static String get(String name, String defaultValue) { return getProps().getProperty(name, defaultValue); } /** Returns the value of the <code>name</code> property as an integer. If no * such property is specified, or if the specified value is not a valid * integer, then <code>defaultValue</code> is returned. */ public static int getInt(String name, int defaultValue) { String valueString = get(name); if (valueString == null) return defaultValue; try { return Integer.parseInt(valueString); } catch (NumberFormatException e) { return defaultValue; } } /** Returns the value of the <code>name</code> property as a long. If no * such property is specified, or if the specified value is not a valid * long, then <code>defaultValue</code> is returned. */ public static long getLong(String name, long defaultValue) { String valueString = get(name); if (valueString == null) return defaultValue; try { return Long.parseLong(valueString); } catch (NumberFormatException e) { return defaultValue; } } /** Returns the value of the <code>name</code> property as a float. If no * such property is specified, or if the specified value is not a valid * float, then <code>defaultValue</code> is returned. */ public static float getFloat(String name, float defaultValue) { String valueString = get(name); if (valueString == null) return defaultValue; try { return Float.parseFloat(valueString); } catch (NumberFormatException e) { return defaultValue; } } /** Returns an input stream attached to the configuration resource with the * given <code>name</code>. */ public static InputStream getConfResourceAsInputStream(String name) { try { URL url= NutchConf.class.getClassLoader().getResource(name); if (url == null) { LOG.info(name + " not found"); return null; } else { LOG.info("found resource " + name + " at " + url); } return url.openStream(); } catch (Exception e) { return null; } } /** Returns a reader attached to the configuration resource with the * given <code>name</code>. */ public static Reader getConfResourceAsReader(String name) { try { URL url= NutchConf.class.getClassLoader().getResource(name); if (url == null) { LOG.info(name + " not found"); return null; } else { LOG.info("found resource " + name + " at " + url); } return new InputStreamReader(url.openStream()); } catch (Exception e) { return null; } } /** Returns the value of the <code>name</code> property as an boolean. If no * such property is specified, or if the specified value is not a valid * boolean, then <code>defaultValue</code> is returned. Valid boolean values * are "true" and "false". */ public static boolean getBoolean(String name, boolean defaultValue) { String valueString = get(name); if ("true".equals(valueString)) return true; else if ("false".equals(valueString)) return false; else return defaultValue; } private static void loadResource(String name, boolean quietFail) { try { URL url = NutchConf.class.getClassLoader().getResource(name); if (url == null) { if (!quietFail) LOG.severe(name + " not found"); return; } else { LOG.info("loading " + url); } Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder() .parse(url.toString()); Element root = doc.getDocumentElement(); if (!"nutch-conf".equals(root.getTagName())) LOG.severe("bad conf file: top-level element not <nutch-conf>"); NodeList props = root.getChildNodes(); for (int i = 0; i < props.getLength(); i++) { Node propNode = props.item(i); if (!(propNode instanceof Element)) continue; Element prop = (Element)propNode; if (!"property".equals(prop.getTagName())) LOG.warning("bad conf file: element not <property>"); NodeList fields = prop.getChildNodes(); String attr = null; String value = null; for (int j = 0; j < fields.getLength(); j++) { Node fieldNode = fields.item(j); if (!(fieldNode instanceof Element)) continue; Element field = (Element)fieldNode; if ("name".equals(field.getTagName())) attr = ((Text)field.getFirstChild()).getData(); if ("value".equals(field.getTagName()) && field.hasChildNodes()) value = ((Text)field.getFirstChild()).getData(); } if (attr != null && value != null) properties.setProperty(attr, value); } } catch (Exception e) { LOG.severe("error parsing conf file: " + e); } } /** For debugging. List all properties to the terminal and exits. */ public static void main(String[] args) { getProps().list(System.out); } }